﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Mail;

namespace MailSharp
{
  public class Mailer
  {
    public SettingsInfo Settings = new SettingsInfo();

    public Mailer(IDbConnection _connection, string _templateFolder, string smtpServer)
    {
      Settings.Connection = _connection;
      if (_templateFolder.EndsWith("\\"))
        Settings.TemplateFolder = _templateFolder;
      else
        Settings.TemplateFolder = _templateFolder + "\\";
      Settings.SmtpServer = smtpServer; 
    }

    public Mailer(IDbConnection _connection, string _templateFolder, string _smtpServer, int _port,
                  string _username, string _password, bool _useSSL)
      : this(_connection, _templateFolder, _smtpServer)
    {
      Settings.SmtpServer = _smtpServer;
      Settings.SmtpServerPort = _port;
      Settings.Username = _username;
      Settings.Password = _password;
      Settings.UseSsl = _useSSL;
    }

    //
    // SendNow variants with and without a template for single or multiple recipients
    //
    #region "SendNow Methods"
    public void SendNow(RecipientInfo recipient, SenderInfo sender, string subject, string EmailContent)
    {
      System.Net.Mail.MailMessage msg;
      TemplateInfo template = new TemplateInfo();
      template.Content = EmailContent;
      msg = CreateEmail(recipient, sender, subject, template);
      bool success = SendMessage(msg);
      DatabaseHelper.ArchiveMessage(Settings.Connection, recipient, sender, template, success);
    }
    public void  SendNowUsingTemplate(RecipientInfo recipient, SenderInfo sender, string subject, string templateName)
    {
      System.Net.Mail.MailMessage msg;
      TemplateInfo template = TemplateInfo.LoadFromFile(this.Settings.TemplateFolder + templateName);
      msg = CreateEmail(recipient, sender, subject, template);
      bool success = SendMessage(msg);
      DatabaseHelper.ArchiveMessage(Settings.Connection, recipient, sender, template, success);
    }
    public void SendNow(List<RecipientInfo> recipients, SenderInfo sender, string subject, string EmailContent)
    {
      foreach (RecipientInfo recip in recipients)
      {
        SendNow(recip, sender, subject, EmailContent);
      }
    }
    public void SendNowUsingTemplate(IEnumerable<RecipientInfo> recipients, SenderInfo sender, string subject, string templateName)
    {
      TemplateInfo template = TemplateInfo.LoadFromFile(Settings.TemplateFolder + templateName);
      foreach (RecipientInfo recip in recipients)
      {
        SendNow(recip, sender, subject, template.Content);
      }
    }
    #endregion

    //
    // SendLater variants with and without a template for single or multiple recipients
    //
    #region "SendLater Methods"
    public void SendLater(RecipientInfo recipient, string EmailContent, DateTime SendDateTime)
    {
      throw new NotImplementedException();
    }
    public void SendLaterUsingTemplate(RecipientInfo recipient, string templateName, DateTime SendDateTime)
    {
      throw new NotImplementedException();
    }
    public void SendLater(List<RecipientInfo> recipients, string EmailContent, DateTime SendDateTime)
    {
      throw new NotImplementedException();
    }
    public void SendLaterUsingTemplate(IEnumerable<RecipientInfo> recipients, string templateName, DateTime SendDateTime)
    {
      throw new NotImplementedException();
    }
    #endregion


    //
    // CreateEmail variants that build the MailMessage object to send.  Both take recipient, 
    // sender, and subject.  One takes a TemplateInfo object. The other takes a string 
    // containing the HTML text and a List of LinkedResource objects.
    //
    #region "CreateEmail Methods"
    private System.Net.Mail.MailMessage CreateEmail(RecipientInfo recipient, SenderInfo sender,
                                                    string subject, TemplateInfo template)
    {
      List<System.Net.Mail.LinkedResource> resources = new List<LinkedResource>();

      string htmlBody = template.Content;

      if (template.ImageFileNames != null)
      {
        int count = 0;
        foreach (string templateFileName in template.ImageFileNames)
        {
          try
          {
            string fileName = null;
            if (System.IO.File.Exists(templateFileName))
            {
              fileName = templateFileName;
            }
            else
            {
              if (System.IO.File.Exists(Settings.TemplateFolder + templateFileName))
              {
                fileName = Settings.TemplateFolder + templateFileName;
              }
            }

            if (fileName != null)
            {
              System.Net.Mail.LinkedResource resource = new System.Net.Mail.LinkedResource(fileName);
              resource.ContentId = "img" + count.ToString();
              resource.ContentType.Name = resource.ContentId;
              if (fileName.EndsWith(".gif")) resource.ContentType.MediaType = System.Net.Mime.MediaTypeNames.Image.Gif;
              if (fileName.EndsWith(".jpg")) resource.ContentType.MediaType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
              resources.Add(resource);
            }
          }
          catch (Exception ex)
          {
            // if opening the file fails, just swallow the exception and move on
          }
        }
      }

      System.Net.Mail.MailMessage msg = CreateEmail(recipient, sender, subject, htmlBody, resources);
      return msg;
    }



    private System.Net.Mail.MailMessage CreateEmail(RecipientInfo recipient, SenderInfo sender,
                                                    string subject, string htmlBody, List<System.Net.Mail.LinkedResource> resources)
    {
      System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
      msg.From = new System.Net.Mail.MailAddress(sender.FromEmail, sender.FromName);
      msg.To.Add(new System.Net.Mail.MailAddress(recipient.RecipientEmail, recipient.RecipientName));
      msg.IsBodyHtml = true;
      if (string.IsNullOrEmpty(sender.Sender) == false)
      {
        msg.Sender = new System.Net.Mail.MailAddress(sender.Sender);
      }
      msg.Subject = subject;
      System.Net.Mail.AlternateView htmlView;
      System.Net.Mail.AlternateView plainView;
      string plainBody = ContentHelper.StripHTML(htmlBody);
      htmlView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(htmlBody, new System.Net.Mime.ContentType("text/html"));
      plainView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(plainBody, new System.Net.Mime.ContentType("text/plain"));
      foreach (System.Net.Mail.LinkedResource r in resources)
      {
        htmlView.LinkedResources.Add(r);
      }
      msg.AlternateViews.Add(plainView);
      msg.AlternateViews.Add(htmlView);
      return msg;
    }
    #endregion


    private bool SendMessage(System.Net.Mail.MailMessage msg)
    {
      System.Net.Mail.SmtpClient _smtp = new System.Net.Mail.SmtpClient();

      _smtp.Host = Settings.SmtpServer;
      _smtp.Port = Settings.SmtpServerPort;

      if (string.IsNullOrEmpty(Settings.Username) == false)
      {

        _smtp.Credentials = new NetworkCredential(Settings.Username, Settings.Password);
      }
      _smtp.EnableSsl = Settings.UseSsl;

      bool success = false;
      int attempts = 0;
      while (attempts < 5 && !success)
      {
        try
        {
          _smtp.Send(msg);
          success = true; 
        }
        catch (Exception ex)
        {
          System.Diagnostics.Debug.WriteLine(ex.Message);
          attempts++;
          System.Threading.Thread.Sleep(123);
        }
      }

      return success;
    }


  }
}
